package polimi.sc.expoquest.storage.datasources;

import java.util.ArrayList;
import java.util.Collection;

import polimi.sc.expoquest.storage.DBContract;
import polimi.sc.expoquest.storage.DBHelper;
import polimi.sc.expoquest.storage.model.Gossip;
import polimi.sc.expoquest.storage.model.GossipComment;
import polimi.sc.expoquest.storage.model.User;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

/**
 * This class is in charge of managing all the database
 * operations related to the GOSSIP_COMMENT TABLE, using the 
 * database helper, which does the direct calls to the 
 * database
 * @author Monica Lozano
 *
 */
public class GossipCommentDataSource {
	//------------------
	//ATTRIBUTES
	//------------------
	/**
	 * The object that represents the database
	 */
	private SQLiteDatabase db;
	/**
	 * The database helper for accessing the database 
	 */
	private DBHelper dbHelper;
	
	//----------------
	// CONSTRUCTOR
	//----------------
	public GossipCommentDataSource(Context ctx)
	{
		//1. We create the DB helper
		dbHelper = new DBHelper(ctx);
	}
	
	//------------------
	//METHODS
	//------------------

	//database connection
	/**
	 * Opens the database such that we can used it for reading and writing
	 */
	public void open(){
		/* 
		 * TODO put this call in a asynchronous task, such that if it takes more than
		 * few seconds our application wont colapse.
		 */
		dbHelper.open();
		db = dbHelper.getWritableDatabase();
	}
	/**
	 * Close the database connection
	 */
	public void close()
	{
		dbHelper.close();
	}
	
	//Database operations
	/**
	 * @param userID: User id from which we want to retrieve the gossip comments
	 * @return the gossip comments saved on the system that belongs to the user with the useID
	 */
	public Collection<GossipComment> getAllGossipsCommentsForUser(int userID)
	{
		//1. Doing the consult
		Cursor cursor = db.query(DBContract.GossipComment.TABLE_NAME,DBContract.GossipComment.ALL_COLUMNS,
										DBContract.GossipComment.CLM_NAME_USER_ID +"="+ userID,null,null,null,null);
		//2. We create the list from the results of the query
		Collection<GossipComment> gossipComments = buildCollectionFromCursor(cursor);
		return gossipComments;
	}
	
	
	/**
	 * @return Returns all the comments done to a gossip, it only returns the users ID and Gossip ID for 
	 * retrieving the remaining data the respective data source must be used
	 */
	public Collection<GossipComment> getAllGossipsCommentsForGossip(int gossipID)
	{
		
		//1. Doing the consult
		Cursor cursor = db.query(DBContract.GossipComment.TABLE_NAME,DBContract.GossipComment.ALL_COLUMNS,
				DBContract.GossipComment.CLM_NAME_GOSSIP_ID +"="+ gossipID,null,null,null,null);
		//2. We create the list from the results of the query
		Collection<GossipComment> gossipComments = buildCollectionFromCursor(cursor);
		return gossipComments;
	}
	/**
	 * @param cursor
	 * @return Builds a collection of gossips based on the results pointed by the given cursor
	 */
	private Collection<GossipComment> buildCollectionFromCursor(Cursor cursor)
	{
		Collection<GossipComment> gossipComments = new ArrayList<GossipComment>();
		cursor.moveToFirst();
		while(!cursor.isAfterLast())
		{
			GossipComment g = cursorToGossipComment(cursor);
			gossipComments.add(g);
			cursor.moveToNext();
		}
		cursor.close();
		return gossipComments;
	}
	
	/**
	 * Inserts a gossip comment</b>
	 * Precondition: The userID is and ID that must already exists on the database, the same for gossipID</b>
	 * Postcondition: The gossip comment is inserted
	 * @param comment: the comment
	 * @param gossipID: the gossip ID
	 * @param userID: the user ID that is creating the gossip, ATTENTION: ID IS DIFFERENT FROM USERNAME
	 * @return
	 */
	public GossipComment insert (String comment, int gossipID, int userID)
	{
		//1.We create the values for saving them into the database
		ContentValues values = generateValues(comment, gossipID, userID);
		//2. We save it on the database
		long insertID= db.insert(DBContract.GossipComment.TABLE_NAME, null, values);
		//3. We return the alarm object saved succesfully into the database
		GossipComment c = getGossipComment(insertID);
		return c;
	}
	/**
	 * @param gossipID
	 * @return returns the gossip that has the given ID, it doesnt include the comments and either the complete information related to the user
	 * for obtaining the remaining data for the user, the user data source must be used.
	 */
	private GossipComment getGossipComment(long gossipCommentID)
	{
		//3. We return the alarm object saved succesfully into the database
		Cursor cursor = db.query(DBContract.GossipComment.TABLE_NAME, 
								DBContract.GossipComment.ALL_COLUMNS, 
								DBContract.GossipComment._ID+ "="+ gossipCommentID, 
								null, null, null, null);
		//3.1. Move the cursor to recent inserted row
		cursor.moveToFirst();
		//3.2. Creating the gossip comment object
		GossipComment g = cursorToGossipComment(cursor);
		//3.3 Closing the cursor
		cursor.close();
		return g;
	}

	/**
	 * Deletes a gossip comment
	 * @param g
	 * @return
	 */
	public boolean delete(GossipComment c)
	{
		long id = c.getId();
		int total= db.delete(DBContract.GossipComment.TABLE_NAME,
				  DBContract.GossipComment._ID+"="+id, null);
		return total>0;
	}	
	/**
	 * Create the values for query
	 * @param comment
	 * @param gossipID
	 * @param userID
	 * @return
	 */
	private ContentValues generateValues(String comment, int gossipID, int userID)
	{
		ContentValues values = new ContentValues();
		values.put(DBContract.GossipComment.CLM_NAME_GOSSIP_ID, gossipID);
		values.put(DBContract.GossipComment.CLM_NAME_COMMENT,comment);
		values.put(DBContract.GossipComment.CLM_NAME_USER_ID, userID);
		return values;
	}
	/**
	 * Creates the gossip comment object from the data in the current cursor
	 * @param cursor
	 * @return A gossip comment structure with the basic data: the comment, gossip ID and the user ID
	 */
	private GossipComment cursorToGossipComment(Cursor cursor)
	{
		GossipComment gc = new GossipComment();
		//1. We obtain the columns indexes based on their names
		int idColIndex = cursor.getColumnIndex(DBContract.GossipComment._ID);
		int commColIndex = cursor.getColumnIndex(DBContract.GossipComment.CLM_NAME_COMMENT);
		int giColIndex= cursor.getColumnIndex(DBContract.GossipComment.CLM_NAME_GOSSIP_ID);
		int userColIndex = cursor.getColumnIndex(DBContract.GossipComment.CLM_NAME_USER_ID);
		//2.We obtain the data from the row based on the index
		int id =  cursor.getInt(idColIndex);
		int gossipID = cursor.getInt(giColIndex);
		String comment = cursor.getString(commColIndex);
		int userID = cursor.getInt(userColIndex);
		//3.We save the data in the object
		gc.setId(id);
		gc.setComment(comment);
		gc.setGossip(new Gossip(gossipID, null,null));
		gc.setUser(new User (userID, null, null));
		return gc;
	}

}
